package com.pan.behavioral.memento.implement;

import javax.swing.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;

public class OriginatorFrame {
    private JFrame frame;
    private DefaultListModel<String> listModel;
    private JTextField inputText;
    private JButton appendButton;
    private JButton restoreButton;

    public OriginatorFrame(){

        frame = new JFrame("Memento");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setSize(80, 120);
        frame.setLayout(null);
        listModel = new DefaultListModel<>();
        JList<String> jList = new JList<>(listModel);
        JScrollPane scrollPane = new JScrollPane(jList);
        scrollPane.setBounds(10, 0, 60, 80);
        inputText = new JTextField();
        inputText.setBounds(80, 5, 60, 20);
        appendButton = new JButton("添加");
        appendButton.setBounds(80, 30, 60, 20);
        appendButton.addActionListener(e -> {
            addList();
            frame.setFocusable(true);
        });
        restoreButton = new JButton("撤销");
        restoreButton.setBounds(80, 60, 60, 20);
        restoreButton.addActionListener(e -> {
            restore();
        });
        KeyListener restoreListener = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_Z) {
                    restore();
                }
            }
        };
        restoreButton.addKeyListener(restoreListener);
        appendButton.addKeyListener(restoreListener);
        inputText.addKeyListener(restoreListener);
        scrollPane.addKeyListener(restoreListener);
        frame.add(restoreButton);
        frame.add(appendButton);
        frame.add(inputText);
        frame.add(scrollPane);
    }
    public void display(){
        frame.setVisible(true);
    }

    private AtomicBoolean addFlag = new AtomicBoolean(true);


    public void addList() {
        for (;addFlag.compareAndSet(true,false);){}
        String item = inputText.getText();
        if (item.length() == 0) return;
        caretaker.push(getStatus());
        listModel.addElement(item);
        for (;addFlag.compareAndSet(false,true);){}
    }
    private Caretaker caretaker;{
        caretaker = new Caretaker();
    }

    public Memento getStatus() {
        return new Memento(listModel.elements());
    }

    public void restoreStatus(Memento memento) {
        if (listModel.getSize() == 0 || memento == null) {
            return;
        }
        listModel.clear();
        listModel.addAll(memento.getStatus());
    }
    public void restore(){
        Memento pop = caretaker.pop();
        restoreStatus(pop);
    }

    class Memento {
        private List<String> list;{
            list = new LinkedList<>();
        }
        private Function<String, Consumer<List<String>>> to = s -> li -> li.add(s);

        protected Memento(Enumeration enumeration) {
            for (; enumeration.hasMoreElements(); ) to.apply((String) enumeration.nextElement()).accept(list);
        }
        protected Collection<String> getStatus() {
            return list;
        }

        @Override
        public String toString() {
            return "Memento{" +
                    "list=" + list +
                    ", to=" + to +
                    '}';
        }
    }

}
